
(function($) {

    $.fn.editableOptions = function(callback) {

        return $(this).each(function() {

            var select = $(this);

            // Bind f2 to dblclick
            // We can't edit all of them so only get the first
            select.keyup(function(e) {
                if (e.keyCode === 113) {
                    select.find('option:selected:first').dblclick();
                }
            });

            select.find('option').dblclick(function() {

                var option = $(this);
                var text = $('<input type="text" />');

                text.css({
                    "position": "absolute",
                    "padding": 0,
                    "margin": 0,
                    "border": "none",
                    "outline": "none",
                });

                // deal with browsers that don't support option css
                if (option.width() === 0) {

                    text.css({
                        "top": select.position().top +
                               parseInt(select.css("marginTop")) +
                               parseInt(select.css("borderTopWidth")) +
                               parseInt(select.css("paddingTop")) +
                               select.attr("selectedIndex") * (parseInt(select.css("font-size")) + 3),
                        "left": select.position().left +
                                parseInt(select.css("marginLeft")) +
                                parseInt(select.css("borderLeftWidth")) +
                                parseInt(select.css("padding-left")),
                        // the select scrollbar seems to be 11 pixels wide
                        "width": select.width() - 11,
                        // set the padding to 1 to make up for the missing border
                        "padding": 1,
                    });

                } else {

                    var position = option.position();

                    text.css({
                        "left": position.left,
                        "top": position.top,
                        "padding-left": option.css("padding-left"),
                        "height": option.height(),
                        "width": option.outerWidth(),
                    });
                }

                var save = function(text) {
                    option.text(text.value);
                    $(text).remove();
                    if (callback !== undefined) {
                        callback(option);
                    }
                };

                text.val(option.text()).
                    keyup(function(e) {
                        // return saves
                        if (e.keyCode === 13) {
                            $(this).blur();
                        // escape cancels
                        } else if (e.keyCode === 27) {
                            $(this).remove();
                        } else if (e.keyCode === 38 || e.keyCode === 40) {
                            // up arrow moves up an option
                            if (e.keyCode === 38) {
                                sibling = option.prev();
                            // down arrow moves down an option
                            } else if (e.keyCode === 40) {
                                sibling = option.next();
                            }
                            if (sibling.length > 0) {
                                option.attr("selected", false); // if multiple
                                save(this);
                                sibling.attr("selected", true).dblclick();
                            }
                        }
                    }).
                    blur(function() {
                        save(this);
                        select.focus();
                    }).
                    insertAfter(select).
                    focus().
                    select();

            });

        });

    };

})(jQuery);
